/**
 *    @file       multicounter.h
 *
 *    @brief      
 *    @details
 *
 *    @version    1.0
 *    @date       01/26/2014 11:54:51 AM
 *
 *    @author     Theophilus (), wangtf418@gmail.com 
 */
#ifndef _BF_MULTICOUNTER_H_
#define _BF_MULTICOUNTER_H_
#include <string>
#include "comdef.h"
#include "atomic_int.h"

class simplecounter
{
public:
	simplecounter(bf_uint_t type, const std::string &name, bf_int32_t cnt = 0)
		: m_type(type), m_name(name), m_count(cnt)
	{

	}

	~simplecounter()
	{

	}

public:
	inline void count(bf_int32_t cnt)
	{
		m_count.add_return(cnt);
	}

	inline bf_int32_t get_count(bf_bool_t ifclear = false)
	{
		if (ifclear)
		{
			return m_count.return_and(0);
		}
		else
		{
			return m_count.get();
		}
	}

public:
	inline bf_uint_t get_type()
	{
		return m_type;
	}
	
	const std::string & get_name()
	{
		return m_name;
	}

private:
	bf_uint_t m_type;
	std::string m_name;
	atomic_int32 m_count;
};

class multicounter
{
public:
	multicounter() : m_begintime(0), m_cnt_size(0), m_mcounter(NULL)
	{

	}

	~multicounter()
	{
		if (m_mcounter)
		{
			for (bf_size_t i = 0; i < m_cnt_size; i ++)
			{
				if (m_mcounter[i])
				{
					delete m_mcounter[i];
				}
			}
			delete [] m_mcounter;
		}
	}

public:
	inline bf_int_t init(const std::string &name, bf_size_t cnt_size)
	{
		if (name.empty() || cnt_size == 0)
		{
			return BF_ERROR;
		}
		m_mcounter = new simplecounter*[cnt_size];
		memset(m_mcounter, 0, sizeof(simplecounter*) * cnt_size);
		m_name = name;
		m_cnt_size = cnt_size;
		m_begintime = time(NULL);
		return BF_OK;
	}

	inline bf_int_t add_counter(bf_uint_t type, const std::string &name)
	{
		if (type < m_cnt_size && m_mcounter[type] == NULL)
		{
			m_mcounter[type] = new simplecounter(type, name);
			return BF_OK;
		}
		return BF_ERROR;
	}

	inline void count(bf_uint_t type, bf_int32_t cnt = 1)
	{
		if (type < m_cnt_size && m_mcounter[type])
		{
			m_mcounter[type]->count(cnt);
		}
	}

	inline bf_int32_t get_count(bf_uint_t type, bf_bool_t ifclear = false)
	{
		if (type < m_cnt_size && m_mcounter[type])
		{
			return m_mcounter[type]->get_count(ifclear);
		}
		else
		{
			return BF_INT32_MAX;
		}
	}

	inline simplecounter get_counter(bf_uint_t type, bf_bool_t ifclear = false)
	{
		if (type < m_cnt_size && m_mcounter[type])
		{
			bf_int32_t cnt = m_mcounter[type]->get_count(ifclear);
			return simplecounter(m_mcounter[type]->get_type(), m_mcounter[type]->get_name(), cnt);
		}
		else
		{
			return simplecounter(0, "", 0);
		}
	}

	inline bf_time_t get_begintime(bf_bool_t ifclear = false)
	{
		bf_time_t time_tmp = m_begintime;
		if (ifclear)
		{
			m_begintime = time(NULL);
		}
		return time_tmp;
	}

	inline std::string & get_name()
	{
		return m_name;
	}

	inline bf_size_t get_cnt_size()
	{
		return m_cnt_size;
	}

private:
	bf_time_t m_begintime;
	std::string m_name;
	bf_size_t m_cnt_size;
	simplecounter **m_mcounter;	
};

#endif

